package cn.nexd.app.collector.presenter.db;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;

import com.umeng.analytics.MobclickAgent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.nexd.sdk.collector.NexdCollectorResult;
import cn.nexd.sdk.collector.bean.BeaconCollectorResult;

/**
 * Created by xun on 2016/8/2.
 */
public class NexdSqlOpenHelper extends SQLiteOpenHelper {
    public static final String DB_NAME = "db_nexd.db";
    private final static int curVersion = 2;
    private static final String CREATE_TABLE_USER = "create table  if not exists " + TableContract.User.TABLE_NAME + " (" + TableContract.User.COLUMN_NAME_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + TableContract.User.COLUMN_NAME_USEREMAIL + "," + TableContract.User.COLUMN_NAME_USERPASSWORD +
            "," + TableContract.User.COLUMN_NAME_USERNAME + ")";
    private static final String CREATE_TABLE_BUILDING = "create table  if not exists " + TableContract.Building.TABLE_NAME + "(" + TableContract.Building.COLUMN_BUILDING_CODE + "," + TableContract.Building.COLUMN_BUILDING_NAME_PY + "," + TableContract.Building.COLUMN_BUILDING_NAME + "," + TableContract.Building.COLUMN_CITY_NAME_PY + "," + TableContract.Building.COLUMN_CITY_NAME + ")";
    private static final String CREATE_TABLE_RECORD = "create table if not exists " + TableContract.Record.TABLE_NAME + " (" + TableContract.Record.COLUMN_NAME_USEREMAIL + "," + TableContract.Record.COLUMN_NAME_ISREMEMBER + " BOOLEAN default 'false')";
    public static final String CREATE_TABLE_CITY = "create table if not exists " + TableContract.City.TABLE_NAME + " (" + TableContract.City.COLUMN_CITY_NAME + "," + TableContract.City.COLUMN_CITY_NAME_PY + ")";
    public static final String CREATE_TABLE_IOS = "create table if not exists " + TableContract.IOS.TABLE_NAME + "(" + TableContract.IOS.COLUMN_MAC_ADDRESS + " primary key ," + TableContract.IOS.COLUMN_UUID + "," + TableContract.IOS.COLUMN_MAJOR + "," + TableContract.IOS.COLUMN_MINOR + ")";
    private SQLiteDatabase db;
    private Context context;

    public NexdSqlOpenHelper(Context context) {
        super(context, DB_NAME, null, curVersion);
        db = getReadableDatabase();
        this.context = context;
    }

    public SQLiteDatabase getDb() {
        return db;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_USER);
        db.execSQL(CREATE_TABLE_BUILDING);
        db.execSQL(CREATE_TABLE_RECORD);
        db.execSQL(CREATE_TABLE_CITY);
        db.execSQL(CREATE_TABLE_IOS);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion > oldVersion) {
            switch (curVersion) {
                //更新

            }
        }
    }

    public boolean tableIsExist(String tableName) {
        boolean result = false;
        if (TextUtils.isEmpty(tableName)) {
            return false;
        }
        String sql = "select count(*) as c from Sqlite_master  where type='table' and name='" + tableName + "'";
        Cursor cursor = db.rawQuery(sql, null);
        if (cursor.moveToNext()) {
            int count = cursor.getInt(0);
            if (count > 0) {
                result = true;
            }
            return result;
        }
        return false;
    }

    public List<NexdCollectorResult> getIOSMess() {
        String sql = "select * from ios";
        Cursor cursor = db.rawQuery(sql, null);
        List<NexdCollectorResult> iOS = new ArrayList<>();
        if (cursor != null) {
            while (cursor.moveToNext()) {
                iOS.add(new NexdCollectorResult(new BeaconCollectorResult(
                        cursor.getString(cursor.getColumnIndex("macAddress")),
                        0.0f,
                        "",
                        cursor.getString(cursor.getColumnIndex("UUID")),
                        cursor.getInt(cursor.getColumnIndex("Major")),
                        cursor.getInt(cursor.getColumnIndex("Minor")),
                        0)));
            }
        }

        if (cursor!=null) {
            cursor.close();
        }
        db.execSQL("delete from ios");
        return iOS;
    }

    public void insertIfNotExist(List<NexdCollectorResult> list) {
        for (NexdCollectorResult nexdCollectorResult : list) {
            String sql = "insert or ignore into ios (macAddress, UUID, Major, Minor) values ('"
                    + nexdCollectorResult.getSingleSourceAddress()
                    + "','" + nexdCollectorResult.getSingleSourceUuid()
                    + "','" + nexdCollectorResult.getSingleSourceMajor()
                    + "','" + nexdCollectorResult.getSingleSourceMinor() + "')";
            db.execSQL(sql);
        }
    }

    public Cursor selectCursor(String sql, String[] selectArgs) {
        return db.rawQuery(sql, selectArgs);
    }

    public int selectCursorSize(String tableName) {
        Cursor cursor = db.query(tableName, null, null, null, null, null, null);
        return cursor.getCount();
    }

    //添加多条数据
    public int insert(List<Map<String, String>> list, String tableName) {
        try {
            db.beginTransaction();
            for (Map<String, String> map : list) {
                ContentValues values = mapToContentValues(map);
                db.insert(tableName, null, values);
                if (values != null) {
                    values.clear();
                }
            }
            db.setTransactionSuccessful();
            return list.size();
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return -1;
        } finally {
            db.endTransaction();
        }
    }

    //更新数据
    public int update(ContentValues values, String stringWhere, String[] stringArgs, String tableName) {
        try {
            int rowNum = db.update(tableName, values, stringWhere, stringArgs);
            return rowNum;
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return -1;
        } finally {
        }
    }

    //添加一条数据
    public int insert(TToMap tToMap, String tableName) {
        try {
            ContentValues contentValues = tToMap.toMap();
            db.insert(tableName, null, contentValues);
            return 1;
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return -1;
        } finally {
        }
    }

    public int insert(ContentValues values, String tableName) {
        try {
            db.insert(tableName, null, values);
            return 1;
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return -1;
        } finally {
        }
    }


    public int delete(String sqlWhere, String[] stringArgs, String tableName) {
        try {
            db.beginTransaction();
            int rowCount = db.delete(tableName, sqlWhere, stringArgs);
            db.setTransactionSuccessful();
            return rowCount;
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return -1;
        } finally {
            db.endTransaction();
        }

    }

    public void deleteAll(String tableName) {
        try {
            db.beginTransaction();
            db.delete(tableName, null, null);
            db.setTransactionSuccessful();
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
        } finally {
            db.endTransaction();
        }
    }


    public interface TToMap {
        ContentValues toMap();
    }

    public void close(Cursor cursor) {
        if (db != null) {
            db.close();
        }
        if (cursor != null) {
            cursor.close();
        }
    }


    public ContentValues mapToContentValues(Map<String, String> map) {
        ContentValues values = new ContentValues();
        for (String key : map.keySet()) {
            values.put(key, map.get(key).toString());
        }
        return values;
    }


    public <T> List<T> query(String sql, String[] stringArgs, ModelT<T> modelT) {
        List<T> list = new ArrayList<T>();
        try {
            Cursor cursor = selectCursor(sql, stringArgs);
            while (cursor.moveToNext()) {
                list.add(modelT.Model(cursor));
            }
            return list;
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return list;
        } finally {
            close();
        }
    }

    public List<Map<String, Object>> selectCursorToList(Cursor cursor) {
        MapModel mapModel = new MapModel();
        List<Map<String, Object>> selectResult = new ArrayList<Map<String, Object>>();
        try {
            while (cursor.moveToNext()) {
                selectResult.add(mapModel.Model(cursor));
            }
            return selectResult;
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return selectResult;
        } finally {
        }
    }

    public <T> Map<String, T> selectCursorToMap(Cursor cursor, ModelT modelT) {
        Map<String, T> map = new HashMap<String, T>();
        try {
            while (cursor.moveToNext()) {
                map.putAll((Map<? extends String, ? extends T>) modelT.Model(cursor));
            }
            return map;
        } catch (Exception e) {
            MobclickAgent.reportError(context, e);
            return map;
        } finally {
            close();
        }
    }


    public interface ModelT<T> {
        T Model(Cursor cursor);
    }


    class MapModel implements ModelT<Map<String, Object>> {

        @Override
        public Map<String, Object> Model(Cursor cursor) {
            String[] columnNames = cursor.getColumnNames();
            Map<String, Object> user = new HashMap<String, Object>();
            for (String columnName : columnNames) {
                user.put(columnName, cursor.getString(cursor.getColumnIndex(columnName)));
            }
            return user;
        }

    }
}
